package com.basic.common.date;

import com.basic.common.string.StringCheckDsUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

/**
 * 日期工具类
 *
 * @author
 * @version v_1.0.1
 * @since
 */
public class DateDsUtil {

    /**
     * 对日期进行格式化
     *
     * @param dateStr
     * @param pattern
     * @return
     */
    public static Date stringToDate(String dateStr, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        try {
            return sdf.parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据时间变量返回时间字符串
     *
     * @param pattern 时间字符串样式
     * @param date    时间变量
     * @return 返回时间字符串
     */
    public static String dateToString(Date date, String pattern) {
        if (date == null) {
            return null;
        }
        try {
            SimpleDateFormat sfDate = new SimpleDateFormat(pattern);
            sfDate.setLenient(false);
            return sfDate.format(date);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 计算两个日期之间相差的天数
     *
     * @param smdate 较小的时间
     * @param bdate  较大的时间
     * @return 相差天数
     * @throws ParseException
     */
    public static int daysBetween(Date smdate, Date bdate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        smdate = sdf.parse(sdf.format(smdate));
        bdate = sdf.parse(sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long betweenDays = (time2 - time1) / (1000 * 3600 * 24);
        return Integer.parseInt(String.valueOf(betweenDays));
    }

    /**
     * 根据Date时间计算相差天数，小时数，分钟数
     *
     * @param sDate
     * @param eDate
     * @return
     */
    public static String getDateInterval(Date sDate, Date eDate) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        long day = 1000 * 24 * 60 * 60;
        long hour = 1000 * 60 * 60;
        long minute = 1000 * 60;
        //两时间相差毫秒数
        long intervalMilli = eDate.getTime() - sDate.getTime();
        //相差天数
        long dayCha = intervalMilli / day;
        //相差小时数
        long hourCha = intervalMilli / hour;
        //相差分钟数
        long minuteCha = intervalMilli / minute;
        int hm = 60;
        int h = 24;
        int m = 30;
        if (minuteCha < hm) {
            if (minuteCha == 0) {
                return String.valueOf(1) + "分钟前";
            } else {
                return String.valueOf(minuteCha) + "分钟前";
            }
        } else if (hourCha < h && hourCha > 0) {
            return String.valueOf(hourCha) + "小时前";
        } else if (dayCha >= 1 && dayCha <= m) {
            return String.valueOf(dayCha) + "天前";
        } else if (dayCha > m) {
            return sdf.format(sDate);
        }
        return null;
    }

    public static String queryDateSpace(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算相差多少天
        long day = diff / nd;
        // 计算相差多少小时
        long hour = diff % nd / nh;
        // 计算相差多少分钟
        long min = diff % nd % nh / nm;
        // 计算相差多少秒//输出结果
        return day + "天" + hour + "小时" + min + "分钟";
    }

    public static String queryDateSpacedDay(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算相差多少天
        long day = diff / nd;
        // 计算相差多少小时
        long hour = diff % nd / nh;
        // 计算相差多少分钟
        long min = diff % nd % nh / nm;
        // 计算相差多少秒//输出结果
        return day + "天";
    }

    /**
     * @param date 操作的日期
     *             patten 需要操作的日期域 例如 天：Calendar.DAY_OF_MONTH; 小时：Calendar.HOUR_OF_DAY
     *             time 需要增加的时间值 例如 -1
     * @auther lishen
     * @date 2015-10-13
     */
    public static Date modifyDate(Date date, int patten, int time) {
        Calendar cal = null;
        try {
            cal = Calendar.getInstance();
            cal.setTime(date);
            cal.add(patten, time);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cal.getTime();
    }

    /**
     * 比较两个时间的 时分秒 大小
     *
     * @param startDate
     * @param endDate
     * @return int startDate > endDate 返回1； 相等返回0 ；startDate < endDate 返回-1
     * @author LiuXiBin
     * @since 2019/6/4 18:03
     **/
    public static int compareToTime(Date startDate, Date endDate) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(startDate);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(endDate);
        //初始化 年月日 为
        cal1.set(DateDsConstant.DATA_INIT_YEAR, DateDsConstant.DATA_INIT_MONTH, DateDsConstant.DATA_INIT_DAY);
        cal2.set(DateDsConstant.DATA_INIT_YEAR, DateDsConstant.DATA_INIT_MONTH, DateDsConstant.DATA_INIT_DAY);

        return cal1.getTime().compareTo(cal2.getTime());
    }

    /**
     * 获取两个日期间的时间间隔
     *
     * @param startTime-起始日期
     * @param endTime-截止日期
     * @param pattern-日期格式
     * @return
     * @author ZhangXu
     * @since 2019.11.1
     */
    public static List<String> fetchDatePeroid(Date startTime, Date endTime, String pattern) throws ParseException {
        List<String> timeList = new ArrayList<String>();
        SimpleDateFormat sd = new SimpleDateFormat(pattern);
        timeList.add(sd.format(startTime));
        Calendar cal = Calendar.getInstance();
        cal.setTime(startTime);
        Calendar calEnd = Calendar.getInstance();
        calEnd.setTime(endTime);
        int field = Calendar.DAY_OF_YEAR;
        if (DateDsConstant.DATE_FORMAT_YYYY.toUpperCase().equals(pattern.toUpperCase())) {
            field = Calendar.YEAR;
        } else if (DateDsConstant.DATE_FORMAT_YYYY_MM.toUpperCase().equals(pattern.toUpperCase())) {
            field = Calendar.MONTH;
        }
        while (sd.parse(sd.format(calEnd.getTime())).after(sd.parse(sd.format(cal.getTime())))) {
            cal.add(field, 1);
            timeList.add(sd.format(cal.getTime()));
        }
        return timeList;
    }

    /**
     * 获取两个日期间的间隔(相隔几年，几个月，几天)
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param pattern   YEAR-年，MON-月，其他-日
     * @return
     * @author LS
     * @date 2019/11/1
     */
    public static int fetchInvelDate(Date startTime, Date endTime, String pattern) {
        if (startTime.after(endTime)) {
            Date temp = endTime;
            endTime = startTime;
            startTime = temp;
        }
        ZoneId znoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(startTime.toInstant(), znoneId);
        LocalDate startLocal = localDateTime.toLocalDate();
        localDateTime = LocalDateTime.ofInstant(endTime.toInstant(), znoneId);
        LocalDate endLocal = localDateTime.toLocalDate();
        Period pd = Period.between(startLocal, endLocal);
        int invert = 0;
        pattern = StringCheckDsUtil.isBlank(pattern) ? "" : pattern;
        if ("YEAR".equals(pattern.toUpperCase())) {
            invert = pd.getYears();
        } else if ("MON".equals(pattern.toUpperCase())) {
            invert = pd.getYears() * 12 + pd.getMonths();
        } else {
            invert = pd.getYears() * 365 + pd.getMonths() * 30 + pd.getDays();
        }
        return invert;
    }

    /**
     * 获得今日前多少数据
     *
     * @param num  数量
     * @param type 类型
     * @return java.util.LinkedList<java.lang.String>
     * @author YanShuang
     * @since 2020/5/20 17:57
     */

    public static LinkedList<String> getBeforeData(int num, String type, boolean isContain) {
        LinkedList<String> strings = new LinkedList<>();
        Date date = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        num = isContain ? num : num + 1;
        if (DateDsConstant.DATE_YEAR.equals(type)) {
            int now = cal.get(Calendar.YEAR);
            cal.add(Calendar.YEAR, -num);
            for (int i = 0; i < num - 1; i++) {
                cal.add(Calendar.YEAR, 1);
                int year = cal.get(Calendar.YEAR);
                strings.add(year + "");
            }
            if (isContain) {
                strings.add(now + "");
            }
        } else if (DateDsConstant.DATE_MONTH.equals(type)) {
            int y = cal.get(Calendar.YEAR);
            int m = cal.get(Calendar.MONTH);
            cal.add(Calendar.MONTH, -num);
            for (int i = 0; i < num - 1; i++) {
                cal.add(Calendar.MONTH, 1);
                int year = cal.get(Calendar.YEAR);
                int month = cal.get(Calendar.MONTH);
                strings.add(year + "-" + (month + 1));
            }
            if (isContain) {
                strings.add(y + "-" + (m + 1));
            }
        } else if (DateDsConstant.DATE_DAY.equals(type)) {
            int y = cal.get(Calendar.YEAR);
            int m = cal.get(Calendar.MONTH);
            int d = cal.get(Calendar.DATE);
            cal.add(Calendar.DATE, -num);
            for (int i = 0; i < num - 1; i++) {
                cal.add(Calendar.DATE, 1);
                int year = cal.get(Calendar.YEAR);
                int month = cal.get(Calendar.MONTH);
                int day = cal.get(Calendar.DATE);
                strings.add(year + "-" + (month + 1) + "-" + day);
            }
            if (isContain) {
                strings.add(y + "-" + (m + 1) + "-" + d);
            }
        }
        return strings;
    }
    public static  List<LocalDateTime> getDateMaxMin(LocalDate date) {
        LocalDateTime maxDate = LocalDateTime.of(date, LocalTime.MAX);

        LocalDateTime minDate = LocalDateTime.of(date, LocalTime.MIN);

        return Arrays.asList(minDate, maxDate);
    }

    public static List<LocalDateTime> getTodayMonthMaxMin(LocalDate today) {
        // 获取本月的第一天
        LocalDate monthMin = today.withDayOfMonth(1);
        LocalDateTime monthTimeMin = LocalDateTime.of(monthMin, LocalTime.MIN);

        // 获取本月的最后一天
        LocalDate monthMax = today.withDayOfMonth(today.lengthOfMonth());
        LocalDateTime monthTimeMax = LocalDateTime.of(monthMax, LocalTime.MAX);

        return Arrays.asList(monthTimeMin, monthTimeMax);
    }
    public static List<LocalDateTime> getTodayYearMaxMin(LocalDate today) {
        LocalDate endOfYear = today.with(TemporalAdjusters.lastDayOfYear());
        LocalDate startOfYear = LocalDate.of(today.getYear(), 1, 1);
        LocalDateTime endTime = LocalDateTime.of(endOfYear, LocalTime.MAX);
        LocalDateTime startTime = LocalDateTime.of(startOfYear, LocalTime.MIN);
        return Arrays.asList(startTime, endTime);
    }
    public static LocalDate dateToLocalDate(Date date) {
        Instant instant = date.toInstant();

        // 指定时区，例如 "Asia/Shanghai"
        ZoneId zoneId = ZoneId.of("Asia/Shanghai");

        // 转换为 LocalDate
        return instant.atZone(zoneId).toLocalDate();
    }
    public static void main(String[] args) {
        LinkedList<String> beforeData = getBeforeData(12, DateDsConstant.DATE_YEAR, true);
        System.out.println(beforeData);
    }
}
